from datetime import datetime, timedelta, date
import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error

from quant import data_utils

DATA_FILE = "d3.csv"


class Options:
    use_win = False
    win_low = 0
    win_high = 0

    use_draw = False
    draw_low = 0
    draw_high = 0

    use_lose = False
    lose_low = 0
    lose_high = 0

    use_rangqiu_num = False
    rangqiu_num_low = 0
    rangqiu_num_high = 0

    use_rangqiu_win = False
    rangqiu_win_low = 0
    rangqiu_win_high = 0

    use_rangqiu_draw = False
    rangqiu_draw_low = 0
    rangqiu_draw_high = 0

    use_rangqiu_lose = False
    rangqiu_lose_low = 0
    rangqiu_lose_high = 0

    def __init__(self):
        pass


def print_hi(name):
    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.


def prepare_options(match, options):
    if (options['use_league']):
        options['league'] = match.league

    if (options['use_rangqiu_num']):
        options['rangqiu_num'] = int(match.rangqiu)

    if (options['use_win']):
        options['win_low'] = round(float(match.win) * (1 - options['margin_of_error']), 2)
        options['win_high'] = round(float(match.win) * (1 + options['margin_of_error']), 2)

    if (options['use_draw']):
        options['draw_low'] = round(float(match.draw) * (1 - options['margin_of_error']), 2)
        options['draw_high'] = round(float(match.draw) * (1 + options['margin_of_error']), 2)

    if (options['use_lose']):
        options['lose_low'] = round(float(match.lose) * (1 - options['margin_of_error']), 2)
        options['lose_high'] = round(float(match.lose) * (1 + options['margin_of_error']), 2)

    if (options['use_rangqiu_win']):
        options['rangqiu_win_low'] = round(float(match.rangqiu_win) * (1 - options['margin_of_error']), 2)
        options['rangqiu_win_high'] = round(float(match.rangqiu_win) * (1 + options['margin_of_error']), 2)

    if (options['use_rangqiu_draw']):
        options['rangqiu_draw_low'] = round(float(match.rangqiu_draw) * (1 - options['margin_of_error']), 2)
        options['rangqiu_draw_high'] = round(float(match.rangqiu_draw) * (1 + options['margin_of_error']), 2)

    if (options['use_rangqiu_lose']):
        options['rangqiu_lose_low'] = round(float(match.rangqiu_lose) * (1 - options['margin_of_error']), 2)
        options['rangqiu_lose_high'] = round(float(match.rangqiu_lose) * (1 + options['margin_of_error']), 2)

    return options


def query_matches(options):
    df = pd.read_csv(DATA_FILE, encoding="UTF-8",
                     usecols=["比赛时间", "联赛", "让球", "赛果", "让球赛果", "总进球", "半全场", "比分", "赛果赔率",
                              "让球赛果赔率", "总进球赔率", "半全场赔率", "比分赔率",
                              "胜", "平", "负", "胜临", "平临", "负临",
                              "让胜临", "让平临", "让负临",
                              "0临", "1临", "2临", "3临",
                              "4临", "5临", "6临", "7临", "总进球"],
                     header=0,
                     low_memory=False,
                     dtype={"0临": float, "1临": float, "2临": float, "3临": float, "4临": float, "5临": float,
                            "6临": float, "7临": float}
                     )
    df = df.dropna()
    df["让球"] = df["让球"].astype(int)
    df["总进球"] = df["总进球"].astype(int)

    start_date = (datetime.now() + timedelta(days=-DAYS)).strftime('%Y-%m-%d')
    end_date = (datetime.now() + timedelta(days=0)).strftime('%Y-%m-%d')

    df['比赛时间'] = pd.to_datetime(df['比赛时间'])
    df = df[(df['比赛时间'] >= start_date) & (df['比赛时间'] <= end_date)]
    if options["use_league"]:
        df = df[df['联赛'] == options["league"]]

    df['让球赛果'] = df['让球赛果'].apply(lambda x: x.replace("让胜", "胜").replace("让平", "平").replace("让负", "负"))

    if options["use_rangqiu_num"]:
        df = df[(df['让球'] == options["rangqiu_num"])]

    if options["use_win"]:
        df = df[(df['胜临'] >= options["win_low"]) & (df['胜临'] <= options["win_high"])]

    if options["use_draw"]:
        df = df[(df['平临'] >= options["draw_low"]) & (df['平临'] <= options["draw_high"])]

    if options["use_lose"]:
        df = df[(df['负临'] >= options["lose_low"]) & (df['负临'] <= options["lose_high"])]

    if options["use_rangqiu_win"]:
        df = df[(df['让胜临'] >= options["rangqiu_win_low"]) & (df['让胜临'] <= options["rangqiu_win_high"])]

    if options["use_rangqiu_draw"]:
        df = df[(df['让平临'] >= options["rangqiu_draw_low"]) & (df['让平临'] <= options["rangqiu_draw_high"])]

    if options["use_rangqiu_lose"]:
        df = df[(df['让负临'] >= options["rangqiu_lose_low"]) & (df['让负临'] <= options["rangqiu_lose_high"])]

    return df


def backtest(match, df):
    if (len(df) == 0):
        print(f'{match.no} 暂无符合场次')
        return

    total = 0
    win_amount = 0
    win_count = 0
    lose_amount = 0
    lose_count = 0
    draw_amount = 0
    draw_count = 0

    rangqiu_win_amount = 0
    rangqiu_win_count = 0
    rangqiu_draw_amount = 0
    rangqiu_draw_count = 0
    rangqiu_lose_amount = 0
    rangqiu_lose_count = 0

    for row in df.itertuples():
        total += 1
        if row.赛果 == "胜":
            win_amount += row.胜临
            # win_amount += float(match.win)
            win_count += 1

        if row.赛果 == "平":
            draw_amount += row.平临
            # draw_amount += float(match.draw)
            draw_count += 1

        if row.赛果 == "负":
            lose_amount += row.负临
            # lose_amount += float(match.lose)
            lose_count += 1

        if row.让球赛果 == "胜":
            rangqiu_win_amount += row.让胜临
            # rangqiu_win_amount += float(match.rangqiu_win)
            rangqiu_win_count += 1

        if row.让球赛果 == "平":
            rangqiu_draw_amount += row.让平临
            # rangqiu_draw_amount += float(match.rangqiu_draw)
            rangqiu_draw_count += 1

        if row.让球赛果 == "负":
            rangqiu_lose_amount += row.让负临
            # rangqiu_lose_amount += float(match.rangqiu_lose)
            rangqiu_lose_count += 1

    win_payback_percent = round(100 * float(match.win) * win_count / total)
    wins_percent = round(100 * win_count / total)
    draw_payback_percent = round(100 * float(match.draw) * draw_count / total)
    draws_percent = round(100 * draw_count / total)
    lose_payback_percent = round(100 * float(match.lose) * lose_count / total)
    losses_percent = round(100 * lose_count / total)

    rangqiu_win_payback_percent = round(100 * rangqiu_win_amount / total)
    rangqiu_wins_percent = round(100 * rangqiu_win_count / total)
    rangqiu_draw_payback_percent = round(100 * rangqiu_draw_amount / total)
    rangqiu_draws_percent = round(100 * rangqiu_draw_count / total)
    rangqiu_lose_payback_percent = round(100 * rangqiu_lose_amount / total)
    rangqiuloses_percent = round(100 * rangqiu_lose_count / total)

    vip_match = False
    if (
            win_payback_percent > COEF or draw_payback_percent > COEF or lose_payback_percent > COEF or rangqiu_win_payback_percent > COEF or rangqiu_draw_payback_percent > COEF or rangqiu_lose_payback_percent > COEF):
        vip_match = True

    win_payback_percent = f'\033[31m{win_payback_percent}\033[0m' if win_payback_percent > 100 else win_payback_percent
    draw_payback_percent = f'\033[31m{draw_payback_percent}\033[0m' if draw_payback_percent > 100 else draw_payback_percent
    lose_payback_percent = f'\033[31m{lose_payback_percent}\033[0m' if lose_payback_percent > 100 else lose_payback_percent

    rangqiu_win_payback_percent = f'\033[31m{rangqiu_win_payback_percent}\033[0m' if rangqiu_win_payback_percent > 100 else rangqiu_win_payback_percent
    rangqiu_draw_payback_percent = f'\033[31m{rangqiu_draw_payback_percent}\033[0m' if rangqiu_draw_payback_percent > 100 else rangqiu_draw_payback_percent
    rangqiu_lose_payback_percent = f'\033[31m{rangqiu_lose_payback_percent}\033[0m' if rangqiu_lose_payback_percent > 100 else rangqiu_lose_payback_percent

    match_no = f'\033[31m{match.no}\033[0m'
    same_count = f'\033[31m{len(df)}\033[0m' if (len(df)) > 25 else len(df)
    print(
        f'{"推荐" if vip_match else "不推荐"}{match_no} {match.endtime} {match.league} {"{:<5}".format(match.home_team)} vs {"{:>5}".format(match.away_team)} '
        f'让球:{match.rangqiu}\n'
        f'    历史同赔: {same_count} '
        f'  (胜:{win_count}|{wins_percent}%|{win_payback_percent}%) '
        f'(平:{draw_count}|{draws_percent}%|{draw_payback_percent}%) '
        f'(负:{lose_count}|{losses_percent}%|{lose_payback_percent}%)       '
        f'(让胜:{rangqiu_win_count}|{rangqiu_wins_percent}%|{rangqiu_win_payback_percent}%) '
        f'(让平:{rangqiu_draw_count}|{rangqiu_draws_percent}%|{rangqiu_draw_payback_percent}%) '
        f'(让负:{rangqiu_lose_count}|{rangqiuloses_percent}%|{rangqiu_lose_payback_percent}%)'
    )

    avg_win = round(win_amount / win_count, 2) if win_count > 0 else 0
    avg_draw = round(draw_amount / draw_count, 2) if draw_count > 0 else 0
    avg_lose = round(lose_amount / lose_count, 2) if lose_amount > 0 else 0

    avg_rangqiu_win = round(rangqiu_win_amount / rangqiu_win_count, 2) if rangqiu_win_count > 0 else 0
    avg_rangqiu_draw = round(rangqiu_draw_amount / rangqiu_draw_count, 2) if rangqiu_draw_count > 0 else 0
    avg_rangqiu_lose = round(rangqiu_lose_amount / rangqiu_lose_count, 2) if rangqiu_lose_amount > 0 else 0

    print(
        f'    胜平负         平均赔率:({avg_win}, {avg_draw}, {avg_lose})                        实际赔率:({match.win, match.draw, match.lose})'
    )
    print(
        f'    让球胜平负      平均赔率:({avg_rangqiu_win, avg_rangqiu_draw, avg_rangqiu_lose})                        实际赔率:({match.rangqiu_win, match.rangqiu_draw, match.rangqiu_lose})'
    )


DAYS = 730
COEF = 1


def run():
    options = {"use_league": False,
               "use_win": True,
               "use_draw": True,
               "use_lose": True,
               "use_rangqiu_num": False,
               "use_rangqiu_win": True,
               "use_rangqiu_draw": True,
               "use_rangqiu_lose": True,
               "margin_of_error": 0.05}
    matches = data_utils.read_matches(0)
    for k in matches.keys():
        match = matches[k]
        options = prepare_options(match, options)
        history_matches = query_matches(options)
        results = backtest(match, history_matches)


if __name__ == '__main__':
    run()
